package com.ktjiaoyu.crm.config;

import com.ktjiaoyu.crm.pojo.Right;
import com.ktjiaoyu.crm.realm.MyShiroRealm;
import com.ktjiaoyu.crm.service.RightService;
import com.ktjiaoyu.crm.service.ShiroService;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName : ShiroConfig
 * @Description :
 * @Author : Lzz
 * @Date: 2023/11/27 10:47:15
 */
@Configuration
public class ShiroConfig {

    //注入 Redis 参数，从 application.properties 获得
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;

    @Resource
    private RightService rightService;

    @Resource
    private ShiroService shiroService;

    /**
     * 哈希凭证匹配器，替换默认的SimpleCredentialsMatcher
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        // 使用 md5 算法进行加密
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        // 设置散列次数： 意为加密几次
        hashedCredentialsMatcher.setHashIterations(2);
        return hashedCredentialsMatcher;
    }

    //配置redisManager
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        return redisManager;
    }

    //配置cacheManager
    public RedisCacheManager cacheManager() {
        RedisCacheManager cacheManager = new RedisCacheManager();
        cacheManager.setRedisManager(redisManager());
        //缓存名称，shiro-redis中默认是id，此处我们改用实体类中的usrName做缓存名称
        cacheManager.setPrincipalIdFieldName("usrName");
        //缓存有效时间
        cacheManager.setExpire(1800);
        return cacheManager;
    }

    //会话操作
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO sessionDAO = new RedisSessionDAO();
        sessionDAO.setRedisManager(redisManager());
        return sessionDAO;
    }

    //会话管理
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
        return sessionManager;
    }

    @Bean   //装配自定义Realm
    public MyShiroRealm myShiroRealm(){
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        //设置启用缓存，并设置缓存名称
        myShiroRealm.setCachingEnabled(true);
        myShiroRealm.setAuthorizationCachingEnabled(true);
        myShiroRealm.setAuthorizationCacheName("authorizationCache");
        //替换默认凭证(密码)匹配器
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myShiroRealm;
    }

    @Bean   //装配安全管理器
    public DefaultWebSecurityManager defaultWebSecurityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //注入自定义Realm
        securityManager.setRealm(myShiroRealm());
        //注入缓存管理器
        securityManager.setCacheManager(cacheManager());
        //注入会话管理器
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }

    @Bean //装配过滤器
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager manager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //注入SecurityManager
        shiroFilterFactoryBean.setSecurityManager(manager);
        //身份认证失败，则跳转到登录页面的配置 没有登录的用户请求需要登录的页面时自动跳转到登录页面，
        //不是必须的属性，不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面
        shiroFilterFactoryBean.setLoginUrl("/toLogin");
        //没有权限默认跳转的页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(shiroService.loadFilterChainDefinitions());
        //权限验证：使用fileter控制资源访问
        return shiroFilterFactoryBean;
    }

}
